﻿#pragma once
#include <iostream>
#include <vector>
#include <string>
using namespace std;


static const int __stl_num_primes = 28;
static const unsigned long __stl_prime_list[__stl_num_primes] =
{
  53,         97,         193,       389,       769,
  1543,       3079,       6151,      12289,     24593,
  49157,      98317,      196613,    393241,    786433,
  1572869,    3145739,    6291469,   12582917,  25165843,
  50331653,   100663319,  201326611, 402653189, 805306457,
  1610612741, 3221225473, 4294967291
};

inline unsigned long __stl_next_prime(unsigned long n)
{
	const unsigned long* first = __stl_prime_list;
	const unsigned long* last = __stl_prime_list + __stl_num_primes;
	const unsigned long* pos = lower_bound(first, last, n);
	return pos == last ? *(last - 1) : *pos;
}

template <class T>
struct Hash_
{
	size_t operator()(T x)
	{
		return (size_t)x;
	}
};

template <>
struct Hash_<string>
{
	size_t operator()(string x)
	{
		size_t hashi = 0;
		for (auto ch : x)
		{
			hashi *= 131;
			hashi += ch;
		}
		return hashi;
	}
};

namespace openadders
{
	enum state
	{
		EXIST,
		DELETE,
		EMPTY
	};

	template<class T>
	struct HashNode
	{
	public:
		T _data = T();
		state _state;
		HashNode()
			:_state(EMPTY)
		{}
	};
	template<class T, class HashFunc = Hash_<T>>
	class hash_table
	{
		typedef HashNode<T> Node;
	public:
		hash_table(unsigned long capcity = __stl_next_prime(0))
			: _size(0)
		{
			_tabe.resize(capcity);
		}

		bool insert(const T& x)
		{

			if (((double)(_size + 1) / (double)_tabe.size()) >= 0.7)
			{
				hash_table tmp(__stl_next_prime(_tabe.size() + 1));

				for (const auto& x: _tabe)
				{
					if (x._state == EXIST)
					{
						tmp.insert(x._data);
					}
				}

				swap(tmp._tabe, _tabe);
				swap(tmp._size, _size);

			}

			int hash0 = Hashfun(x) % _tabe.size();
	
			if (_tabe[hash0]._state == EMPTY|| _tabe[hash0]._state == DELETE )
			{
				_tabe[hash0]._data = x;
				_tabe[hash0]._state = EXIST;
				_size++;
				return true;
			}
			int i = 1;
			int hashi = (hash0 + i) % _tabe.size();
			while (_tabe[hashi]._state == EXIST)
			{
				i++;
				hashi = (hash0 + i) % _tabe.size();
			}

			_tabe[hashi]._data = x;
			_tabe[hashi]._state = EXIST;
			_size++;
			
			return true;
		}
		bool find(const T& x)
		{
			int hash0 = Hashfun(x) % _tabe.size();
			if (_tabe[hash0]._data == Hashfun(x) && _tabe[hash0]._state == EXIST)
			{

				return true;
			}
			else if(_tabe[hash0]._data == Hashfun(x) && _tabe[hash0]._state != EXIST)
			{
				return false;
			}

			int i = 1;
			int hashi = (hash0 + i) % _tabe.size();

			while (_tabe[hashi]._data != Hashfun(x) && hashi!= hash0)
			{
				i++;
				hashi = (hash0 + i) % _tabe.size();
			}

			
			if (_tabe[hashi]._state == DELETE || _tabe[hashi]._state == EMPTY || hashi == hash0)
			{
				return false;
			}
			else
			{
				return true;
			}
		}

		// 哈希桶中删除key的元素，删除成功返回true，否则返回false
		bool erase(const T& x)
		{
			int hash0 = Hashfun(x) % _tabe.size();
			if (_tabe[hash0]._data == Hashfun(x) && _tabe[hash0]._state == EXIST)
			{
				_tabe[hash0]._state = DELETE;
				return true;
			}
			else if (_tabe[hash0]._data == Hashfun(x) && _tabe[hash0]._state != EXIST)
			{
				return false;
			}


			int i = 1;
			int hashi = (hash0 + i) % _tabe.size();

			while (_tabe[hashi]._data != Hashfun(x) && hashi != hash0)
			{
				i++;
				hashi = (hash0 + i) % _tabe.size();
			}


			if (_tabe[hashi]._state == DELETE || _tabe[hashi]._state == EMPTY || hashi == hash0)
			{
				return false;
			}
			else
			{
				_tabe[hashi]._state = DELETE;
				return true;
			}

		}


	private:
		vector<Node> _tabe;
		unsigned long _size;
		HashFunc Hashfun;
	};

}











namespace hash_bucket
{
	template<class K,class T>
	struct HashNode
	{
		pair<K,T> _data;
		HashNode<K,T>* _next;
		HashNode(const pair<K, T>& data)
			:_data(data)
			, _next(nullptr)
		{}
	};
	



	template<class K, class T, class HashFunc = Hash_<K>>
	class HashTable
	{

		typedef HashNode<K, T> Node;
	public:
		HashTable()
		{
			_tables.resize(11, nullptr);
		}

		// 哈希桶的销毁
		~HashTable()
		{
			for (size_t i = 0; i < _tables.size(); i++)
			{
				Node* cur = _tables[i];
				Node* next = nullptr;
				while (cur)
				{
					next = cur->_next;
					delete cur;
					cur = next;
					
				}
				_tables[i] = nullptr;
			}
			
		}


		// 插入值为data的元素，如果data存在则不插入
		bool insert(const pair<K, T>& data)
		{

			if (_n == _tables.size())
			{
				
				vector<Node*> newtbale(__stl_next_prime(_tables.size() + 1), nullptr);
				for (size_t i = 0; i < _tables.size(); i++)
				{
					if (_tables[i])
					{
						Node* cur = _tables[i];
						Node* next = nullptr;
						while (cur)
						{
							next = cur->_next;
							int hash0 = Hashfun(cur->_data.first) % newtbale.size();
							cur ->_next = newtbale[hash0];
							newtbale[hash0] = cur;

						}

					
					}
					_tables[i] = nullptr;
				}
				
				_tables.swap(newtbale);

			}
			if (find(data.first))
			{
				return false;
			}

			int hash0 = Hashfun(data.first) % _tables.size();
			Node* cur = new Node(data);
			cur->_next = _tables[hash0];
			_tables[hash0] = cur;
			_n++;

			return true;
		}

		// 在哈希桶中查找值为key的元素，存在返回true否则返回false﻿
		bool find(const K& key)
		{
			int hash0 = Hashfun(key) % _tables.size();
			Node* cur = _tables[hash0];
			while (cur)
			{
				if (cur->_data.first == key)
				{
					return true;
				}
				cur = cur->_next;
			}
			return false;
		}

		// 哈希桶中删除key的元素，删除成功返回true，否则返回false
		bool erase(const K& key)
		{
			int hash0 = Hashfun(key) % _tables.size();
			Node* prev = nullptr;
			Node* cur = _tables[hash0];
			while (cur)
			{
				
				if (cur->_data.first == key)
				{
					if (prev == nullptr)
					{
						_tables[hash0] = cur->_next;
					}
					else
					{
						prev->_next = cur->_next;

					}
					delete cur;
					return true;
				}
				prev = cur;
				cur = cur->_next;
			}
			return false;

		}

	private:
		vector<Node*> _tables;  // 指针数组
		size_t _n = 0;			// 表中存储数据个数
		HashFunc Hashfun;
	};
}